pub mod event_t {
    pub enum Msg {
        InputValue(String),
    }

    use wasm_bindgen::JsCast;
    use web_sys::{EventTarget, HtmlInputElement, console};
    use yew::{
        events::Event,
        html,
        Component, Context, Html,
    };
    use weblog::*;

    pub struct  JsCastEventComp;

    impl Component for JsCastEventComp {
        // Msg::InputValue(String)
        type Message = Msg;

        type Properties = ();

        fn create(_ctx: &Context<Self>) -> Self {
            Self
        }
        fn update(&mut self, _ctx: &Context<Self>, msg: Self::Message) -> bool {
            match msg {
                Msg::InputValue(value) => {
                    // print in the web console
                    console_log!(value.clone());
                    true
                }
            }
        }

        // two pass msg way cautious / dangerous
        fn view(&self, ctx: &Context<Self>) -> Html {
            let link = ctx.link();
            // using batch_callback if something unexpected happens will return None and do nothing.
            let on_cautious_change = link.batch_callback(|e: Event| {
                // when events are crated the target is undefined, it's only when dispatched does the target get added.
                let target: Option<EventTarget> = e.target();
                // Event can bubble so this listener might catch events from child elements which are not of type HtmlInputElement.
                let input = target.and_then(|t| t.dyn_into::<HtmlInputElement>().ok());
                input.map(|input| Msg::InputValue(input.value()))
            });
            let on_dangerous_change = link.callback(|e: Event| {
                let target: EventTarget = e
                    .target()
                    .expect("Event should have a target when dispatched");
                    // target is a HtmlInputElement, otherwise the call to value would be Undefined Behavior.
                Msg::InputValue(target.unchecked_into::<HtmlInputElement>().value())
            });
            html! {
                <div>
                    <label for="cautious-input">
                        {"My cautious-input:"}
                        <input 
                            type="text"
                            id="cautious-input"
                            onchange={on_cautious_change}
                        />
                    </label>
                    <br/>
                    <label for="dangerous-input">
                        {"My dangerous-input:"}
                        <input 
                            type="text"
                            id="dangerous-input"
                            onchange={on_dangerous_change}
                        />
                    </label>
                </div>
            }
        }
    }
}